package com.dronff.interceptor;

import com.dronff.BlockSend;
import com.dronff.Result;
import com.dronff.protocol.TangProtocol;
import com.dronff.stat.ProtocolType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.Function;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class TangProtocolRPCProxyObjectInterceptor implements MethodInterceptor {
    private BlockSend blockSend;
    /**
     * 结果映射，线程唤醒后通过这个方法获取请求的结果
     */
    public static Map<String, Result> resultMap = new ConcurrentHashMap<>();
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        String reqId = UUID.randomUUID().toString();
        Parameter[] parameters = method.getParameters();
        String[] paramTypes = new String[parameters.length];
        final int[] i = {0};
        Arrays.stream(parameters).forEach(
                new Consumer<Parameter>() {
                    @Override
                    public void accept(Parameter parameter) {
                        paramTypes[i[0]++] = parameter.getParameterizedType().getTypeName();
                    }
                }
        );
        TangProtocol protocol = TangProtocol
                .builder()
                .methodName(method.getName())
                .params(objects)
                .methodTypes(paramTypes)
                .clazzName(method.getDeclaringClass().getCanonicalName())
                .type(ProtocolType.INVOKE)
                .reqId(reqId)
                .build();
        // 发送该数据后会阻塞线程
        blockSend.sendTangProtocolData(protocol,(object)->{
            resultMap.put(reqId,new Result(object,null));
        });
        return (resultMap.get(reqId)).getResult();
    }

}
